home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / xform.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  8.2 KB  |  263 lines

  1. /* $Id: xform.c,v 1.5 1997/01/03 23:54:17 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: xform.c,v $
  26.  * Revision 1.5  1997/01/03 23:54:17  brianp
  27.  * changed length threshold in gl_xform_normals_3fv() to 1E-30 per Jeroen
  28.  *
  29.  * Revision 1.4  1996/11/09 01:50:49  brianp
  30.  * relaxed the minimum normal threshold in gl_xform_normals_3fv()
  31.  *
  32.  * Revision 1.3  1996/11/08 02:20:39  brianp
  33.  * added gl_xform_texcoords_4fv()
  34.  *
  35.  * Revision 1.2  1996/11/05 01:38:50  brianp
  36.  * fixed some comments
  37.  *
  38.  * Revision 1.1  1996/09/13 01:38:16  brianp
  39.  * Initial revision
  40.  *
  41.  */
  42.  
  43.  
  44. /*
  45.  * Matrix/vertex/vector transformation stuff
  46.  *
  47.  *
  48.  * NOTES:
  49.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  50.  * 2. Points/vertices are to be thought of as column vectors.
  51.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  52.  *
  53.  */
  54.  
  55.  
  56.  
  57. #include <math.h>
  58. #include "types.h"
  59. #include "xform.h"
  60.  
  61.  
  62.  
  63.  
  64.  
  65. /*
  66.  * Apply a transformation matrix to an array of [X Y Z W] coordinates:
  67.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  68.  * where p[i] and q[i] are 4-element column vectors and m is a 16-element
  69.  * transformation matrix.
  70.  */
  71. void gl_xform_points_4fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  72.                           GLfloat p[][4] )
  73. {
  74.    /* This function has been carefully crafted to maximize register usage
  75.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  76.     * will like this code too.
  77.     */
  78.    {
  79.       GLuint i;
  80.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  81.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  82.       if (m12==0.0F && m13==0.0F) {
  83.          /* common case */
  84.          for (i=0;i<n;i++) {
  85.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  86.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2;
  87.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2;
  88.          }
  89.       }
  90.       else {
  91.          /* general case */
  92.          for (i=0;i<n;i++) {
  93.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  94.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12 * p3;
  95.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13 * p3;
  96.          }
  97.       }
  98.    }
  99.    {
  100.       GLuint i;
  101.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  102.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  103.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  104.          /* common case */
  105.          for (i=0;i<n;i++) {
  106.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  107.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  108.             q[i][3] = p3;
  109.          }
  110.       }
  111.       else {
  112.          /* general case */
  113.          for (i=0;i<n;i++) {
  114.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  115.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  116.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15 * p3;
  117.          }
  118.       }
  119.    }
  120. }
  121.  
  122.  
  123.  
  124. /*
  125.  * Apply a transformation matrix to an array of [X Y Z] coordinates:
  126.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  127.  */
  128. void gl_xform_points_3fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  129.                           GLfloat p[][3] )
  130. {
  131.    /* This function has been carefully crafted to maximize register usage
  132.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  133.     * will like this code too.
  134.     */
  135.    {
  136.       GLuint i;
  137.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  138.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  139.       for (i=0;i<n;i++) {
  140.          GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  141.          q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12;
  142.          q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13;
  143.       }
  144.    }
  145.    {
  146.       GLuint i;
  147.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  148.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  149.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  150.          /* common case */
  151.          for (i=0;i<n;i++) {
  152.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  153.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  154.             q[i][3] = 1.0F;
  155.          }
  156.       }
  157.       else {
  158.          /* general case */
  159.          for (i=0;i<n;i++) {
  160.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  161.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  162.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15;
  163.          }
  164.       }
  165.    }
  166. }
  167.  
  168.  
  169.  
  170. /*
  171.  * Apply a transformation matrix to an array of normal vectors:
  172.  *   for i in 0 to n-1 do  v[i] = u[i] * m
  173.  * where u[i] and v[i] are 3-element row vectors and m is a 16-element
  174.  * transformation matrix.
  175.  * If the normalize flag is true the normals will be scaled to length 1.
  176.  */
  177. void gl_xform_normals_3fv( GLuint n, GLfloat v[][3], const GLfloat m[16],
  178.                            GLfloat u[][3], GLboolean normalize )
  179. {
  180.    if (normalize) {
  181.       /* Transform normals and scale to unit length */
  182.       GLuint i;
  183.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  184.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  185.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  186.       for (i=0;i<n;i++) {
  187.          GLdouble tx, ty, tz;
  188.          {
  189.             GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  190.             tx = ux * m0 + uy * m1 + uz * m2;
  191.             ty = ux * m4 + uy * m5 + uz * m6;
  192.             tz = ux * m8 + uy * m9 + uz * m10;
  193.          }
  194.          {
  195.             GLdouble len, scale;
  196.             len = sqrt( tx*tx + ty*ty + tz*tz );
  197.             scale = (len>1E-30) ? (1.0 / len) : 1.0;
  198.             v[i][0] = tx * scale;
  199.             v[i][1] = ty * scale;
  200.             v[i][2] = tz * scale;
  201.          }
  202.       }
  203.    }
  204.    else {
  205.       /* Just transform normals, don't scale */
  206.       GLuint i;
  207.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  208.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  209.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  210.       for (i=0;i<n;i++) {
  211.          GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  212.          v[i][0] = ux * m0 + uy * m1 + uz * m2;
  213.          v[i][1] = ux * m4 + uy * m5 + uz * m6;
  214.          v[i][2] = ux * m8 + uy * m9 + uz * m10;
  215.       }
  216.    }
  217. }
  218.  
  219.  
  220.  
  221. /*
  222.  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
  223.  * function is used for transforming clipping plane equations and spotlight
  224.  * directions.
  225.  * Mathematically,  u = v * m.
  226.  * Input:  v - input vector
  227.  *         m - transformation matrix
  228.  * Output:  u - transformed vector
  229.  */
  230. void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
  231. {
  232.    GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
  233. #define M(row,col)  m[col*4+row]
  234.    u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
  235.    u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
  236.    u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
  237.    u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
  238. #undef M
  239. }
  240.  
  241.  
  242.  
  243. /*
  244.  * Apply a transformation matrix to an array of [S T R Q] texture coordinates:
  245.  *   for i in 0 to n-1 do   tc[i] = m * tc[i]
  246.  */
  247. void gl_xform_texcoords_4fv( GLuint n, GLfloat tc[][4], const GLfloat m[16] )
  248. {
  249.    GLfloat m0 = m[0], m4 = m[4],  m8 = m[ 8], m12 = m[12];
  250.    GLfloat m1 = m[1], m5 = m[5],  m9 = m[ 9], m13 = m[13];
  251.    GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
  252.    GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
  253.    GLint i;
  254.  
  255.    for (i=0;i<n;i++) {
  256.       GLfloat t0 = tc[i][0], t1 = tc[i][1], t2 = tc[i][2], t3 = tc[i][3];
  257.       tc[i][0] = m0 * t0 + m4 * t1 +  m8 * t2 + m12 * t3;
  258.       tc[i][1] = m1 * t0 + m5 * t1 +  m9 * t2 + m13 * t3;
  259.       tc[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3;
  260.       tc[i][3] = m3 * t0 + m7 * t1 + m11 * t2 + m15 * t3;
  261.    }
  262. }
  263.